//ns3 modules
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"//P2P
//ndnSIM module
#include "ns3/ndnSIM-module.h"//The header contains content store functions, don't need to add more lib.
#include "ns3/gtk-config-store.h"

using namespace ns3;
using namespace ns3::ndn;//introduce ns3

NS_LOG_COMPONENT_DEFINE("ContenStoreLCD");//global definition


static void
DynamicSetAttribute (void)
{
  static int speed=1000;
  for(int i=0;i<6;i++)
  {

    std::stringstream str,str1,str2,str3;
     str<<"/NodeList/"<<i<<"/DeviceList/"<<0<<"/$ns3::PointToPointNetDevice/DataRate";
     //p2pHelper.SetChannelAttribute("Delay",StringValue("10ms"));
     str1<<speed<<"Kbps";
    Config::Set(str.str(),StringValue(str1.str()));
    //std::cout<<str.str()<<std::endl;
  }
  speed+=1;
Simulator::Schedule (MilliSeconds(100), &DynamicSetAttribute);
}

int main(int argc, char *argv[])
{
    //LogComponentEnable("ndn.Consumer", LOG_LEVEL_ALL);
    //LogComponentEnable("ndn.ConsumerZipfMandelbrot", LOG_LEVEL_ALL);
    LogComponentEnable("ndn.Producer", LOG_LEVEL_ALL);
  CommandLine cmd;
  cmd.Parse(argc, argv);

  Config::SetDefault("ns3::QueueBase::MaxSize", StringValue("20p"));
    

    StackHelper ndnHelper;//ndn
    //ndnHelper.Install();
    NodeContainer nodes;
    nodes.Create(7);//Create 6 nodes

    
    PointToPointHelper p2pHelper;//draw line
    
    p2pHelper.SetDeviceAttribute("DataRate",StringValue("1Mbps"));
    p2pHelper.SetChannelAttribute("Delay",StringValue("10ms"));
    for(int i=0;i<5;i++)p2pHelper.Install(nodes.Get(i),nodes.Get(i+1));
    p2pHelper.Install(nodes.Get(4),nodes.Get(6));

    //ndnHelper.SetContentStore ("ns3::ndn::cs::Lru", "MaxSize", "0");
    ndnHelper.setPolicy("nfd::cs::lru");
    ndnHelper.setCsSize(10);
    ndnHelper.SetDefaultRoutes(true);//routes 1,2,3
    for(int i=1;i<4;i++)
        ndnHelper.Install(nodes.Get(i));//Install NDN For each node
    ndnHelper.Install(nodes.Get(5));
    ndnHelper.setCsSize(0);
    ndnHelper.Install(nodes.Get(4));
    ndnHelper.Install(nodes.Get(0));
    ndnHelper.Install(nodes.Get(6));
    AppHelper appSer("ns3::ndn::Producer");
    appSer.SetPrefix("/test");
    appSer.SetAttribute("PayloadSize", StringValue("10240"));
    appSer.Install(nodes.Get(5));


    AppHelper consumerHelper("ns3::ndn::ConsumerZipfMandelbrot");
    consumerHelper.SetPrefix("/test");
    consumerHelper.SetAttribute("Frequency", StringValue("1"));        // 100 interests a second
    consumerHelper.SetAttribute("NumberOfContents", StringValue("1")); // 10 different contents
    consumerHelper.SetAttribute("q", StringValue("0.7000"));// zipf
    consumerHelper.SetAttribute("s", StringValue("0"));
    //0 LCE
    //1 LCD
    //2 Prob0.3
    //3 Prob0.5
    //4 Prob0.7
    consumerHelper.SetAttribute("CacheMode", StringValue("1"));
    // consumerHelper.SetAttribute ("Randomize", StringValue ("uniform")); // 100 interests a second
    consumerHelper.Install(nodes.Get(0));//client
    consumerHelper.SetAttribute("Frequency", StringValue("1"));
    //consumerHelper.Install(nodes.Get(6));
    /*
    AppHelper appCli("ns3::ndn::ConsumerCbr");
    appCli.SetPrefix("/test");
    appCli.SetAttribute("Frequency", StringValue("1"));
    //appCli.SetAttribute("PayloadSize", StringValue("1024"));
    appCli.Install(nodes.Get(0));*/
        
    L3RateTracer::InstallAll("rate-trace.txt", Seconds(30.0));//Get Test Data
    CsTracer::InstallAll("cs-trace.txt", Seconds(30.0));
    DynamicSetAttribute();
    //Simulator::Schedule (MilliSeconds(0), &DynamicSetAttribute);
    //Simulator::Schedule (Seconds (15.0), &DynamicSetAttribute,"5Mbps","100ms");
    //Simulator::Schedule (Seconds (30.0), &DynamicSetAttribute,"100Mbps","100ms");
    Simulator::Stop(Seconds(30.0));
    /* False
    p2pHelper.SetDeviceAttribute("DataRate",StringValue("1Mbps"));
   p2pHelper.SetChannelAttribute("Delay",StringValue("30ms"));
   for(int i=0;i<5;i++)p2pHelper.Install(nodes.Get(i),nodes.Get(i+1));
   */
    //   GtkConfigStore config;
    //config.ConfigureDefaults ();
    //config.ConfigureAttributes ();
    Simulator::Run();
    Simulator::Destroy();

}